﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml.Linq;

namespace Codeplus.Library.Web
{
    public class Geolocation
    {
        public GeolocationModel GetLocation(string ipaddress)
        {
            var requestUrl = string.Format("http://api.hostip.info/?ip={0}&position=true", ipaddress);
            string locationData;
            using (var webClient = new WebClient())
            {
                try
                {
                    locationData = webClient.DownloadString(requestUrl);
                }
                catch (Exception ex)
                {
                    throw new GeolocationFailureException(string.Format("Geolocation failed for ip: {0}", ipaddress), ex);
                }
            }
            if (string.IsNullOrEmpty(locationData))
            {
                throw new GeolocationFailureException(string.Format(
                    "Geolocation returned an empty response for ip: {0}", ipaddress));
            }

            try
            {
                var result = Parse(locationData);
                return result;
            }
            catch (Exception ex)
            {
                throw new GeolocationFailureException(
                    string.Format("Geolocation parsing failed for ip: {0}", ipaddress), ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="locationData"></param>
        /// <returns></returns>
        public static GeolocationModel Parse(string locationData)
        {
            var xmlResponse = XDocument.Parse(locationData);
            var gml = (XNamespace)"http://www.opengis.net/gml";
            var result = (from x in xmlResponse.Descendants("Hostip")
                          let value = x.Element(gml + "name").Value
                          let countryName = x.Element("countryName").Value
                          let countryCode = x.Element("countryAbbrev").Value
                          let longitudeValue = x.Descendants(gml + "coordinates").SingleOrDefault()
                          let longitude =
                              longitudeValue == null ? 0.00F : float.Parse(longitudeValue.Value.Split(',')[1])
                          let latitudeValue = x.Descendants(gml + "coordinates").SingleOrDefault()
                          let latitude = latitudeValue == null ? 0.00F : float.Parse(latitudeValue.Value.Split(',')[0])
                          select new GeolocationModel()
                                     {
                                         CountryCode = countryCode,
                                         CountryName = countryName,
                                         Latitude =
                                             latitude,
                                         Longitude =
                                             longitude,
                                         City = value
                                     })
                .SingleOrDefault();
            return result;
        }
    }
}
